iT邦幫忙

2022 iThome 鐵人賽

DAY 20
0
Software Development

離開C#新手村的最後試煉系列 第 20

# 試煉20 - string 不變性

  • 分享至 

  • xImage
  •  

開始試煉

string 是很特別的 是參考型別 但是使用起來跟實值型別一樣
就來聊聊string為何這樣的特殊吧

不變性Immutability

string的不變性意思就是指 每個string都是獨立的
你只要編輯過 就是產生另一個新string
舉例

var demo = "a";
demo = "a"+"b";

這樣 其實產生了兩個string 一個是a 一個是ab
然後a用不到了GC會去回收
所以才會有一些建議少用 + 字串 多用 string builder
建議在迴圈裡面組字串的話 用 string builder 是比較保險的
其實觀念就是這樣
來看點code

void Main()
{
    var name1 = "Peter";
    var name2A = "Pe";
    var name2B = "ter";
    var name2 = name2A + name2B;
    var name3 = new string(new Char[] { 'P', 'e', 't', 'e', 'r' });
    $"{name1} {name2} {name3}".Dump();
    Object.ReferenceEquals(name1, name2).Dump("name1 Equal name2");
    Object.ReferenceEquals(name2, name3).Dump("name2 Equal name3");
    Object.ReferenceEquals(name1, name3).Dump("name1 Equal name3");
}


明明都是Peter字串的記憶體位置是完全不同的

如果只是這樣應該很好懂但錯了 因為這樣也太浪費記憶體了
所以net做了一件事情

String Pool

String Pool 就是把一樣的字串 共用記憶體
前提是 編譯時 一樣的字串
看code

void Main()
{
	var name1 = "Peter";
	var name2 = "Peter";
	$"{name1} {name2}".Dump();
	Object.ReferenceEquals(name1, name2).Dump("name1 Equal name2");
}


雖然剛剛說過不變性 現在記憶體位置又是相等?!到底是怎
注意看程式碼 這次兩個都是寫死的字串 再編譯時就一樣了
上一個範例是執行時才產生出相同的Peter
這時候其實就是Peter這個字串進入了 String Pool
下次有遇到有人又要Peter 我就給你我String Pool裡面的Peter
你不用在去佔一塊記憶體了
也可以把字串加入到String Pool
使用String.Intern

void Main()
{
    var name1 = "Peter";
    var name2 = "Peter";
    Object.ReferenceEquals(name1, name2).Dump("name1 Equal name2");

    var name3A = "Pe";
    var name3B = "ter";
    var name3 = String.Intern(name3A + name3B);
    Object.ReferenceEquals(name1, name3).Dump("name1 Equal name3");
}


這樣Peter都是指向同一個記憶體位置了

延伸試驗

主廚由實戰面發現了這個問題加上圖文詳解值得一看
[食譜好菜] 從 C# 一個簡單的 lock string 修正了對 String Pool 的觀念

結束試煉

想不到天天都在用的string 如此複雜吧

參考
[.Net Concept]理解並善用String pool


上一篇
# 試煉19 - String Format 多的是你不知道的事
下一篇
# 試煉21 - LINQ 中超好用的DefaultIfEmpty
系列文
離開C#新手村的最後試煉30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言